# -*- coding: utf-8 -*-
import scrapy
from scrapy import Request,FormRequest
import urllib.request



class LoginSpider(scrapy.Spider):
    name = 'login'
    allowed_domains = ['douban.com']
    base_url = "https://www.douban.com/people/207298490/"   #登录成功之后跳转的页面

    def start_requests(self):
        url1="https://accounts.douban.com/passport/login" #登陆页面（不要去豆瓣首页登录）
        return [Request(url=url1, meta={'cookiejar': 1}, callback=self.post_login)]
    """
        return [Request("https://www.douban.com/", meta={"cookiejar": 1}, callback=self.parse)]
        return [Request("https://accounts.douban.com/j/mobile/login/basic", meta={"cookiejar": 1},method="POST",callback=self.parse)]   #我草泥马！！！！！！这里也必须加上——method="POST"
        #return [Request("https://accounts.douban.com/passport/login", meta={"cookiejar": 1}, callback=self.parse)]     #但是他妈的这句不用加，估计这个是真正POST的网址
    """

    def post_login(self,response):
        #爬取当前的页面，查看有无滑块
        #
        captcha = response.xpath("//img[@id='captcha_image']/@src").extract()
        if len(captcha) > 0:
            print("此时有验证码")
            #将验证码存储到本地
            localpath = "C:/Users/DELL/Desktop/豆瓣登陆验证码.png"
            urllib.request.urlretrieve(captcha[0], filename=localpath)
            captcha_value=input("请到C:/Users/DELL/Desktop/豆瓣登陆验证码.png中查看验证码是什么？")
            captcha_value = captcha_value
            print("当前验证码自动识别结果为：" + captcha_value)
            postData = {
                'ck': '',
                'name': '13759903699',
                'password': '421138db',
                'remember': 'false',
                'ticket': ''
            }
        else:
            # 设置要传递的post信息，此时没有验证码字段
            postData = {
                'ck': '',
                'name': '13759903699',
                'password': '421138db',
                'remember': 'false',
                'ticket': ''
            }
        print("登录中…")
        """
           3.使用scrapy.FormRequest()进行登陆，对设置的url发送post请求，对得到的cookies进行存储
                   既然让函数自己去找表单行不通，那我们就自己来呗。不过在这里同样需要用到FormRequest()，只是不再使用from_response()。

                   而是用了FormRequest实例，手动指定post地址，meta参数同样是要带上的，将response.meta[‘cookiejar’]赋值给cookiejar，供后面的Request使用

                   在start_requests中，会默认使用start_urls里面的url来构造Request，在这里我们直接在Request中指定了url（start_urls就没用了），
                   让spider先去访问豆瓣首页（以获取一些隐藏的表单项，在豆瓣登陆里其实并没有什么隐藏的表单项）。
                   start_requests必须返回应该可迭代的对象，因此我们在return后面加了‘[ ]’。之后通过回调函数来发送post请求。

                   在post_login中，我们指定访问方式为post，通过meta参数将response.meta[‘cookiejar’]赋值给cookiejar，供后续的Request使用，并不进行过滤处理。
                   在登陆成功之后，通过回调函数用得到的cookies来生成我们要抓取的页面的Request，同样不进行过滤处理。

        """
        #通过FormRequest进行登陆
        return FormRequest(
            url='https://accounts.douban.com/j/mobile/login/basic',
            method='POST',  # 指定访问方式
            formdata=postData,
            meta={'cookiejar': response.meta['cookiejar']},
            dont_filter=True,  # 不进行去重处理
            callback=self.after_login
        )

    def after_login(self, response):
        print("登陆成功！正在跳转至我的豆瓣")
        url = self.base_url
        yield Request(url=url, meta={'cookiejar': 1}, callback=self.parse, dont_filter=True)

    def parse(self, response):
        print("我的豆瓣（标题）：")
        title = response.xpath("/html/head/title/text()").extract()
        print(title)

"""
未解决的问题1：登陆验证滑块的处理
"""



"""
问题1：我们一直以为时用户代理出现了问题（403错误），其实不是，是没有加——method="POST"，这也会导致403错误
问题2：settings里面设置了用户代理，这里就不用了
"""


"""
模拟登陆
    用Scrapy来进行模拟登陆的方法主要有三种：

    1.自己直接登陆网站，将登陆成功的cookies保存下来，供Scrapy直接携带
        对于该方法不进行展开，毕竟有些网站的cookies会发生变化，短时间内保存下来的cookies再进行模拟登陆时会成功，但是过段时间就不行，因此，对于这种方法并不推荐。当然，没有其他办法的时候，还是可以使用该类方法的（如登陆时需要验证码，验证码较为复杂，或者由一些加密的难以破解的数据）
    2.使用scrapy.Formrequest.from_response()进行登陆， 自动解析当前登陆url，找到表单，发送post请求
        该方法对于大对数网站来说应该都可以实现，因为它能够实现自动解析得到表单，并发送post请求，这能给我们的编程带来极大的便利。 该方法的关键就是对表单进行填写，然后通过scrapy.Formrequest.from_response()进行提交便可以了，在这过程中from_response()用来模拟表单上的提交单击。

        这里callback回调函数设置的是需要登陆成功后才能进行的一些网页请求。
        
        很不幸的是，在使用该方法进行模拟登陆时，Scrapy的某条Debug显示为403
        2019-02-25 22:52:55 [scrapy.core.engine] DEBUG: Crawled (403) <GET https://accounts.douban.com/j/mobile/login/basic> (referer: None)
        并且报错信息（截取部分）为：
        raise ValueError("No <form> element found in %s" % response)
        ValueError: No <form> element found in <403 https://accounts.douban.com/j/mobile/login/basic>

        通过报错信息我们知道时，在解析的response中并没有表单信息存在，这是因为from_response()会对得到的response进行form表单的提取，因此在使用该方法时，
        一定要确保response中有form表单，否则，都会出现上述的错误，比如我们这里的豆瓣登陆界面就时不存在form表单的，用浏览器打开请求链接，我们只能看到如下的界面(一般都是空白的界面)
        因此，在这里想让该方法可行，只需要将start_urls内容修改为https://accounts.douban.com/passport/login即可。
        但是根本不用改，因为使用了def start_requests(self)方法
        
    3.使用scrapy.FormRequest()进行登陆，对设置的url发送post请求，对得到的cookies进行存储
        既然让函数自己去找表单行不通，那我们就自己来呗。不过在这里同样需要用到FormRequest()，只是不再使用from_response()。

        而是用了FormRequest实例，手动指定post地址，meta参数同样是要带上的，将response.meta[‘cookiejar’]赋值给cookiejar，供后面的Request使用
        
        在start_requests中，会默认使用start_urls里面的url来构造Request，在这里我们直接在Request中指定了url（start_urls就没用了），
        让spider先去访问豆瓣首页（以获取一些隐藏的表单项，在豆瓣登陆里其实并没有什么隐藏的表单项）。
        start_requests必须返回应该可迭代的对象，因此我们在return后面加了‘[ ]’。之后通过回调函数来发送post请求。
        
        在post_login中，我们指定访问方式为post，通过meta参数将response.meta[‘cookiejar’]赋值给cookiejar，供后续的Request使用，并不进行过滤处理。在登陆成功之后，通过回调函数用得到的cookies来生成我们要抓取的页面的Request，同样不进行过滤处理。

    (***)到目前为止，我们的工作已经完成99%了，就差最后一步了。为了能够让Request加入直接登陆后的cookies信息，我们需要在settings.py中的DOWNLOADER_MIDDLEWARES开启中间件scrapy.downloadermiddlewares.cookies.CookiesMiddleware
        关于中间件的更多信息可参阅:http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/settings.html#std:setting-DOWNLOADER_MIDDLEWARES_BASE

        由于豆瓣中存在着反爬虫机制，所以我们还需要增加User-Agent来伪装成浏览器，在这里为了省事儿，我们直接在settings.py中进行了修改

"""